home *** CD-ROM | disk | FTP | other *** search
/ Tech Arsenal 1 / Tech Arsenal (Arsenal Computer).ISO / tek-05 / driverss.zip / 82586.ASM < prev    next >
Assembly Source File  |  1991-02-11  |  25KB  |  977 lines

  1. i82586_version    equ    2
  2.   ifndef DAN
  3. DAN    equ    4            ; 4 seems to work best.
  4.   endif
  5.  
  6. ;
  7. ; Code that is common between 82586 implementations.
  8. ;
  9.  
  10. ; Ported from Tim Krauskopf's micnet.asm, an assembly language
  11. ; driver for the MICOM-Interlan NI5210, by Russell Nelson.  Any bugs
  12. ; are due to Russell Nelson.
  13. ; Updated to version 1.08 Feb. 17, 1989 by Russell Nelson.
  14. ; Updated to support 1500 byte MTU April 27, 1989 By Brad Clements.
  15.  
  16. ; Copyright, 1988-90, Russell Nelson
  17.  
  18. ;   This program is free software; you can redistribute it and/or modify
  19. ;   it under the terms of the GNU General Public License as published by
  20. ;   the Free Software Foundation, version 1.
  21. ;
  22. ;   This program is distributed in the hope that it will be useful,
  23. ;   but WITHOUT ANY WARRANTY; without even the implied warranty of
  24. ;   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  25. ;   GNU General Public License for more details.
  26. ;
  27. ;   You should have received a copy of the GNU General Public License
  28. ;   along with this program; if not, write to the Free Software
  29. ;   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  30.  
  31. ;
  32. ;  Structure elements specific to the Intel 82586 chip
  33. ;
  34.  
  35. ; System Configuration Pointer
  36. scp_struc    struc
  37. scp_bus        db    ?,?,?, ?,?,?    ; bus use flag (0=16 bit, 1=8 bit).
  38. scp_ptr        dd    ?        ; 24pointer to iscp
  39. scp_struc    ends
  40.  
  41. ; Intermediate System Configuration Pointer
  42. iscp_struc    struc
  43. iscp_busy    db    ?,?        ; busy flag (zeroed after init).
  44. iscp_offset    dw    ?        ; 16pointer to iscp
  45. iscp_base    dd    ?        ; base for all 16 pointers, lo, hi
  46. iscp_struc    ends
  47.  
  48. ; System Control Block
  49. scb_struc    struc
  50. scb_stat    dw    ?        ; status
  51. scb_com        dw    ?        ; command
  52. scb_cbl        dw    ?        ; 16pointer to command block list
  53. scb_rfa        dw    ?        ; 16pointer to receive frame list
  54. scb_serrs    dw    4 dup(?)    ; 4 words of error counts
  55. scb_struc    ends
  56.  
  57. ; (Received) Frame Descriptor
  58. fd_struc    struc
  59. fd_status    dw    ?        ; status word for frame
  60. fd_eol        dw    ?        ; end of FD list flag
  61. fd_link        dw    ?        ; 16pointer to next FD
  62. fd_ptr        dw    ?        ; 16pointer to list of RBD's
  63. fd_dest        db    EADDR_LEN dup(?); 48 bits of destination
  64. fd_source    db    EADDR_LEN dup(?); 48 bits of source
  65. fd_cnt        dw    ?        ; length field of frame.
  66. fd_struc    ends
  67.  
  68. ; Receive Buffer Descriptor
  69. rbd_struc    struc
  70. rbd_status    dw    ?        ; status word in RBD
  71. rbd_link    dw    ?        ; 16pointer to next RBD
  72. rbd_ptr        dd    ?        ; 24pointer to actual buffer
  73. rbd_size    dw    ?        ; size of the buffer
  74. rbd_struc    ends
  75.  
  76. ; Transmit Command Block
  77. tcb_struc    struc
  78. tcb_status    dw    ?        ; status word for xmit
  79. tcb_com        dw    ?        ; command to transmit
  80. tcb_link    dw    ?        ; 16pointer to next command
  81. tcb_ptr        dw    ?        ; 16pointer to xmit TBD
  82. tcb_addr    db    EADDR_LEN dup(?); destination address
  83. tcb_len        dw    ?
  84. tcb_struc    ends
  85.  
  86. ; Transmit Buffer Descriptor
  87. tbd_struc    struc
  88. tbd_status    dw    ?        ; bit 15=EOF, 13-0=actual count
  89. tbd_link    dw    ?        ; 16pointer to next TBD
  90. tbd_ptr        dd    ?        ; 24pointer to buffer
  91. tbd_struc    ends
  92.  
  93. ; all commands have at least the following:
  94. cmd_struc    struc
  95. cmd_status    dw    ?        ; status word
  96. cmd_com        dw    ?        ; command word.
  97. cmd_struc    ends
  98.  
  99. ; MC-SETUP Command Block
  100. mcb_struc    struc
  101. mcb_status    dw    ?        ; status word for multicast
  102. mcb_com        dw    ?        ; command to setup multicast
  103. mcb_link    dw    ?        ; 16pointer to next command
  104. mcb_cnt        dw    ?        ; number of multicast addresses.
  105. mcb_struc    ends
  106.  
  107. ; TDR Command Block
  108. tdr_struc    struc
  109. tdr_status    dw    ?        ; status word for TDR
  110. tdr_com        dw    ?        ; command to setup TDR
  111. tdr_link    dw    ?        ; 16pointer to next command
  112. tdr_time    dw    ?        ; error bits and time
  113. tdr_struc    ends
  114.  
  115. ;Memory allocation.
  116.  
  117. SCPTR    EQU    0fff6h            ; hardwired address for SCP
  118. ISCPTR    EQU    0ffeeh            ; my address for ISCP, points to SCB
  119. SCB    EQU    ISCPTR - 16        ; system control block base
  120. CCBPTR    EQU    SCB - 18        ; offset of configure command block
  121. TBDPTR    EQU    CCBPTR - 8        ; xmit BD offset
  122. TCBPTR    EQU    TBDPTR - 16        ; xmit CB offset
  123. TBUFPTR    EQU    TCBPTR - GIANT        ; xmit buffer offset
  124. ;the receive buffers appear at lower addresses than TBUFPTR.
  125. RBUFLEN    EQU    200
  126. RBUF_TOTAL    equ    (size fd_struc) + (size rbd_struc) + RBUFLEN
  127. FDBASE        equ    TBUFPTR - RBUF_TOTAL
  128.  
  129. memory_begin    dw    ?
  130.  
  131.     public    rcv_modes
  132. rcv_modes    dw    7        ;number of receive modes in our table.
  133.         dw    0               ;There is no mode zero
  134.         dw    0
  135.         dw    rcv_mode_2
  136.         dw    rcv_mode_3
  137.         dw    rcv_mode_4    ;haven't set up perfect filtering yet.
  138.         dw    0
  139.         dw    rcv_mode_6
  140.  
  141. firstfd        dw    FDBASE        ; start of FD queue
  142. lastfd        dw    0        ; end of the FD chain
  143. lastbd        dw    0        ; end of the BD chain
  144. flag        dw    0
  145.  
  146.  
  147. ;
  148. ; Configuration block for 82586, this comprises one config command
  149. ;  Parameters taken from MICOM driver
  150. ;
  151. CBCONF    DW    0        ; status word
  152.     DW    8002H        ; end of command list + configure command
  153.     DW    0ffffh        ; link to next command (not used)
  154.     DW    080CH        ; fifo=8, byte count=C
  155.     DW    2E00H        ; important! Addr (AL) not inserted on the fly!
  156.     DW    6000H        ; IFS = 60h
  157.     DW    0F200H        ; retry=F, slot time=200h
  158. CBCONF_FLAGS    label    byte
  159.     DW    0        ; flags, set to 1 for promiscuous
  160. CBCONF_MINLEN    label    byte
  161.     DW    40H        ; min frame length=40h
  162.  
  163.  
  164. doca_wait:
  165. ;enter with ax = command to execute, es = base_addr.
  166. ;exit with nc if the command ran to completion.
  167. ;exit with cy if the command timed out.  Eventually we'll also reset the chip.
  168.     mov    es:[SCB].scb_com,ax    ;set the command.
  169.  
  170.     mov    si,es:[SCB].scb_cbl    ;
  171.     mov    es:[si].cmd_status,0    ; status word of specific command
  172.     and    ax,0700h
  173.     cmp    ax,0100h        ; is it an action command?
  174.     jne    doca_wait_a        ; no, any other
  175.  
  176.     call    doca
  177.  
  178. comment \
  179. Quoting from the D-Step Errata Revision 2.0:
  180.  
  181. The value for the deadman timer should be greater than the longest
  182. command execution time.  The command which can take the longest time
  183. to execute is the transmit command, assuming maximum retries.  To
  184. determine the maximum amount of time the transmit command may take,
  185. one must use the following equation: 7143 ST + 14 f, where ST stands
  186. for Slot Time and f = Maximum Frame Size + IFS + Preamble.  For
  187. Ethernet/IEEE 802.3 where ST = 512 bits, f = 12144 bits, Preamble =
  188. 64 bits, IFS  96 bits, and one bit = 0.1 usec, the deadman timeout
  189. should be greater than 0.369 seconds.
  190.  
  191. \
  192.  
  193.     mov    ax,14            ;36.4 ticks / seconds * .369 seconds
  194.     call    set_timeout
  195. doca_wait_1:
  196.     test    es:[si].cmd_status,8000h    ; is command complete?
  197.     jnz    doca_wait_2        ;yes.
  198.     call    do_timeout        ;did we time out yet?
  199.     jne    doca_wait_1        ;not yet.
  200. ;reset the chip here, then Configure, IA-Setup, and MC-Setup.
  201.     stc                ;timeout -- uh-oh.
  202.     ret
  203. doca_wait_2:
  204.     clc
  205.     ret
  206.  
  207. doca_wait_a:
  208.     call    doca
  209. doca_wait_a_0:
  210.     cmp    es:[SCB].scb_com,0    ; has the command been accepted?
  211.     jnz    doca_wait_a_0        ; not yet.
  212.     clc
  213.     ret
  214.  
  215.  
  216.     include    timeout.asm
  217.     include    movemem.asm
  218.  
  219.     public    as_send_pkt
  220. ; The Asynchronous Transmit Packet routine.
  221. ; Enter with es:di -> i/o control block, ds:si -> packet, cx = packet length,
  222. ;   interrupts possibly enabled.
  223. ; Exit with nc if ok, or else cy if error, dh set to error number.
  224. ;   es:di and interrupt enable flag preserved on exit.
  225. as_send_pkt:
  226.     ret
  227.  
  228.     public    drop_pkt
  229. ; Drop a packet from the queue.
  230. ; Enter with es:di -> iocb.
  231. drop_pkt:
  232.     assume    ds:nothing
  233.     ret
  234.  
  235.     public    xmit
  236. ; Process a transmit interrupt with the least possible latency to achieve
  237. ;   back-to-back packet transmissions.
  238. ; May only use ax and dx.
  239. xmit:
  240.     assume    ds:nothing
  241.     ret
  242.  
  243.  
  244.     public    send_pkt
  245. send_pkt:
  246. ;enter with es:di->upcall routine, (0:0) if no upcall is desired.
  247. ;  (only if the high-performance bit is set in driver_function)
  248. ;enter with ds:si -> packet, cx = packet length.
  249. ;exit with nc if ok, or else cy if error, dh set to error number.
  250.     assume    ds:nothing
  251.     mov    es,base_addr        ; base for board
  252.  
  253.     cmp    cx,GIANT        ; Is this packet too large?
  254.     ja    send_pkt_toobig
  255.  
  256.     mov    dx,cx            ; save a copy, might be less than 60, ok
  257.  
  258.     cmp    dx,RUNT            ; minimum length for Ether
  259.     jnb    oklen
  260.     mov    dx,RUNT            ; make sure size at least RUNT
  261. oklen:
  262.     mov    di,TBUFPTR        ; start of xmit buffer
  263.  
  264. ;
  265. ;  check for previous xmit
  266. ;
  267. xwait:
  268.     mov    bx,es:[SCB].scb_com    ; has previous command been accepted?
  269.     or    bx,bx
  270.     jnz    xwait            ; not there yet, wait for it
  271. wait_for_transmit_to_complete:
  272.     test    word ptr es:[TCBPTR],4000h
  273.     jnz    wait_for_transmit_to_complete
  274. ;
  275. ;  move the data using word moves.
  276. ;
  277.     call    movemem
  278. ;
  279. ;  put the correct size into the TBD
  280. ;
  281.     or    dx,08000h            ; end of frame bit flag
  282.     mov    es:[TBDPTR].tbd_status,dx    ; store it
  283.     mov    es:[TCBPTR].tcb_status,0    ; zero status wd
  284.     mov    es:[TCBPTR].tcb_com,8004h    ; xmit command in TCB
  285.     mov    es:[SCB].scb_com,0100h        ; execute command
  286.     mov    es:[SCB].scb_cbl,TCBPTR    ; say where xmit command is
  287.  
  288.     call    doca
  289.  
  290.     clc
  291.     ret
  292. send_pkt_toobig:
  293.     mov    dh,NO_SPACE
  294.     stc
  295.     ret
  296.  
  297.  
  298. rcv_mode_2:
  299.     and    CBCONF_FLAGS,not 3
  300.     or    CBCONF_FLAGS,2        ;disable broadcasts.
  301.     mov    CBCONF_MINLEN,40h
  302.     jmp    short reconfigure
  303. rcv_mode_4:
  304. rcv_mode_3:
  305.     and    CBCONF_FLAGS,not 3    ;clear promiscuous mode.
  306.     mov    CBCONF_MINLEN,40h
  307.     jmp    short reconfigure
  308. rcv_mode_6:
  309.     and    CBCONF_FLAGS,not 3
  310.     or    CBCONF_FLAGS,1        ;set promiscuous mode.
  311.     mov    CBCONF_MINLEN,0        ;allow runts.
  312. reconfigure:
  313.     mov    es,base_addr        ;get the base address for the board.
  314.     mov    si,offset CBCONF    ; configure command
  315.     mov    di,CCBPTR        ; where command will reside
  316.     mov    cx,9
  317.     rep    movsw            ; copy to board
  318. ;
  319. ;  issue the configure command
  320. ;
  321.     mov    es:[SCB].scb_cbl,CCBPTR    ; where conf command is
  322.     mov    es:[SCB].scb_serrs[0],0    ; zero errs field
  323.     mov    es:[SCB].scb_serrs[2],0    ; zero errs field
  324.     mov    es:[SCB].scb_serrs[4],0    ; zero errs field
  325.     mov    es:[SCB].scb_serrs[6],0    ; zero errs field
  326.     mov    ax,100h            ; do-command command
  327.     call    doca_wait
  328.     ret
  329.  
  330.  
  331.     public    set_multicast_list
  332. set_multicast_list:
  333. ;enter with ds:si ->list of multicast addresses, cx = number of addresses.
  334. ;return nc if we set all of them, or cy,dh=error if we didn't.
  335.     assume    ds:code
  336.     mov    es,base_addr
  337.     mov    es:[SCB].scb_cbl,TBUFPTR    ;use the transmit buffer.
  338.  
  339.     mov    es:[TBUFPTR].mcb_status,0    ;status word
  340.     mov    es:[TBUFPTR].mcb_com,08003h    ;command word for mc-setup + EL
  341.     mov    es:[TBUFPTR].mcb_link,-1    ;no command link.
  342.     mov    di,TBUFPTR + mcb_cnt
  343.     mov    ax,cx            ;store the count.
  344.     stosw
  345.     rep    movsb
  346.  
  347. comment \ avoid deferred execution of a CU command during reception.
  348. If a command is executed with a length of 18 to 20 bytes, and a frame
  349. is received, the 82586 may deadlock with HOLD active.  We avoid this
  350. problem by suspending the receiver. \
  351.  
  352.     mov    ax,30h            ;suspend frame receiving.
  353.     call    doca_wait
  354.  
  355.     mov    ax,100h            ; do-command command
  356.     call    doca_wait
  357.     jnc    set_multicast_2
  358.  
  359.     mov    ax,20h            ;resume frame receiving.
  360.     call    doca_wait
  361.  
  362.     mov    dh,NO_MULTICAST        ;for some reason we can't do multi's.
  363.     stc
  364.     ret
  365. set_multicast_2:
  366.     mov    ax,20h            ;resume frame receiving.
  367.     call    doca_wait
  368.  
  369.     clc
  370.     ret
  371.  
  372.  
  373.     public    terminate
  374. terminate:
  375.     assume    ds:code
  376.     ret
  377.  
  378.     public    reset_interface
  379. reset_interface:
  380. ;reset the interface.
  381. ;we don't do anything.
  382.     assume    ds:nothing
  383.     ret
  384.  
  385.  
  386. ;called when we want to determine what to do with a received packet.
  387. ;enter with cx = packet length, es:di -> packet type, dl = packet class.
  388.     extrn    recv_find: near
  389.  
  390. ;called after we have copied the packet into the buffer.
  391. ;enter with ds:si ->the packet, cx = length of the packet.
  392.     extrn    recv_copy: near
  393.  
  394.     extrn    count_in_err: near
  395.     extrn    count_out_err: near
  396.  
  397.     public    recv
  398. recv:
  399.   ifdef IO_INTCLR
  400.     loadport            ;clear the interupt latch.
  401.     setport    IO_INTCLR
  402.     out    dx,al
  403.   endif
  404.  
  405.     mov    flag, 1
  406. ;called from the recv isr.  All registers have been saved, and ds=cs.
  407. ;Upon exit, the interrupt will be acknowledged.
  408. recv1:
  409.     mov    ds,base_addr    ; base for board
  410.     assume    ds:nothing
  411.  
  412.     mov    ax,ds:[SCB].scb_stat    ;get the status.
  413. recv_isr_1:
  414.     cmp    ds:[SCB].scb_com,0    ;has previous command been accepted?
  415.     jne    recv_isr_1        ;no -- keep waiting.
  416.  
  417.     and    ax,0f000h        ;isolate the ACK bits to make a
  418.                     ;  command to ack the interrupt.
  419.   if DAN and 1
  420.     jz    recv_isr_2
  421.   endif
  422.  
  423.     mov    ds:[SCB].scb_com,ax    ;set the command.
  424.     call    doca
  425. recv_isr_2:
  426.     cmp    ds:[SCB].scb_com,0    ; has the command been accepted?
  427.     jnz    recv_isr_2        ; not yet.
  428.  
  429. ;  Get whatever packets are on the board
  430. ;
  431.     mov    bx,firstfd    ; get addr of first FD in list
  432.     mov    ax,[bx].fd_status    ; status word of frame
  433.     test    ax,08000h    ; frame written?
  434.     jnz    okframe
  435.  
  436.     jmp    ru_start    ; no, restore receiver if necessary
  437. frame_bad:
  438.     call    count_in_err
  439. ptrupdate_j_1:
  440.     jmp    ptrupdate
  441.  
  442. ;  we have a frame, read it in
  443. ;
  444. okframe:
  445.     test    ax,02000h        ;check frame OK bit
  446.     jz    frame_bad        ;bad, fix it.
  447.     mov    si,[bx].fd_ptr        ;get pointer to buffer descriptor
  448.     xor    cx,cx            ;start with zero bytes.
  449. countbuf:                ;es:di is already set to receive packet
  450.     mov    dx,si            ;save a copy of current BD ptr
  451.     mov    ax,[si].rbd_status    ;get status and count word for BD
  452.     test    ax,04000h        ;is count field there?
  453.     jz    ptrupdate_j_1        ;no - we give up here.
  454.     add    cl,al            ;add the count into cx.
  455.     adc    ch,0
  456.     mov    si,[si].rbd_link    ;go to next BD in list
  457.     test    ax,8000h        ;is this the last frame?
  458.     je    countbuf        ;no - keep counting.
  459.  
  460.     push    bx
  461.     push    cx
  462.  
  463.     mov    ax,cs            ;we need ds = code.
  464.     mov    ds,ax
  465.     assume    ds:code
  466.  
  467.     mov    es,base_addr        ;get a pointer to their type.
  468.     mov    di,es:[bx].fd_ptr    ;get pointer to buffer descriptor
  469.     mov    di,es:[di].rbd_ptr.offs    ;get offset of data
  470.     add    di,EADDR_LEN+EADDR_LEN    ;skip the ethernet addreses and
  471.                     ;  point to the packet type.
  472.  
  473.     mov    dl, BLUEBOOK        ;assume bluebook Ethernet.
  474.     mov    ax, es:[di]
  475.     xchg    ah, al
  476.     cmp     ax, 1500
  477.     ja    BlueBookPacket
  478.     inc    di            ;set di to 802.2 header
  479.     inc    di
  480.     mov    dl, IEEE8023
  481. BlueBookPacket:
  482.     call    recv_find        ;look up our type.
  483.  
  484.     pop    cx
  485.     pop    bx
  486.     mov    ds,base_addr        ;restore ds to the board.
  487.     assume    ds:nothing
  488.  
  489.     mov    ax,es            ;is this pointer null?
  490.     or    ax,di
  491.     je    ptrupdate        ;yes - just free the frame.
  492.  
  493.     push    cx
  494.     push    es            ;remember where the buffer pointer is.
  495.     push    di
  496.   if DAN and 2
  497.     push    cx
  498.   endif
  499.  
  500.     mov    si,[bx].fd_ptr        ;get pointer to buffer descriptor
  501. copybuf:
  502.     mov    dx,si            ;save a copy of current BD ptr
  503.     xor    ch,ch            ;200 bytes is largest this can be
  504.     mov    cl,byte ptr [si].rbd_status;get count word for BD
  505.     mov    si,[si].rbd_ptr.offs    ;get offset of data
  506.   if DAN and 2
  507.     pop    ax
  508.     sub    ax, cx
  509.     jc    copydone
  510.     push    ax
  511.   ENDIf
  512.     call    movemem
  513.     mov    si,dx            ;get back current BD ptr
  514.     test    [si].rbd_status,8000h    ;check EOF bit
  515.     mov    si,[si].rbd_link    ;go to next BD in list
  516.     jz    copybuf            ;not done, keep copying it.
  517.  
  518.   if DAN and 2
  519.     pop    cx
  520. copydone:
  521.   endif
  522.     pop    si            ;now give the frame to the client.
  523.     pop    ds
  524.     pop    cx
  525.     assume    ds:nothing
  526.  
  527.     call    recv_copy
  528. ;
  529. ;  we are done with the frame, do the list management
  530. ;
  531. ptrupdate:
  532.     push    cs
  533.     pop    ds
  534.     assume    ds:code
  535.     mov    es,base_addr        ; reload board segment
  536.  
  537.     mov    si,es:[bx].fd_ptr    ; first BD in frame list
  538. nextbd:
  539.     mov    cx,es:[si].rbd_status    ; count word for BD, EOF bit
  540.     test    cx,08000h        ; EOF bit, if set, save si in lastbd
  541.     jnz    dolastbd
  542.     mov    es:[si].rbd_status,0    ; clear status word, EOF bit
  543.     cmp    si,lastbd        ; see if we are wrapping
  544.     jz    dolastbd        ; yes, just undo it
  545.     mov    si,es:[si].rbd_link    ; follow link
  546.     jmp    nextbd
  547. dolastbd:
  548.     mov    di,lastbd        ; where end of BD list is now
  549.     mov    lastbd,si        ; store last known BD
  550.     mov    es:[si].rbd_size,08000h+200; end of list here
  551.     mov    es:[si].rbd_status,0    ; clear status word, EOF bit
  552. ; size field for not end of list
  553.     mov    es:[di].rbd_size,200    ; remove old end-of-list
  554.  
  555. ;
  556. ;  update the FD list flags, new end-of-list
  557. ;
  558.     mov    es:[bx].fd_eol,08000h    ; store new EOL
  559.     mov    es:[bx].fd_status,0    ; clear status word for frame
  560.     mov    di,lastfd        ; get old end-of-list
  561.     mov    es:[di].fd_eol,0    ; zero old one
  562.     mov    lastfd,bx        ; update stored pointer
  563.     mov    si,es:[bx].fd_link    ; where next fd is
  564.     mov    firstfd,si        ; store that info for next time
  565.   if DAN and 4
  566.     jmp    recv1
  567.   endif
  568.  
  569. ru_start:
  570. ; re-start receive unit
  571. ;
  572. ;  check to see if the receiver went off because of no resources
  573. ;  and restart receiver if necessary
  574. ;
  575.     push    cs
  576.     pop    ds
  577.     mov    es,base_addr
  578.     mov    ax,es:[SCB].scb_stat    ; status word for SCB
  579.     and    ax,070h        ; receiver status
  580.     cmp    al,020h        ; receiver has no resources
  581.     jnz    hasres
  582.   if DAN and 8
  583.     cmp    flag, 1
  584.     jnz    ru_start1
  585.     mov    flag, 0
  586.     jmp    recv1
  587.   endif
  588.  
  589. ru_start1:
  590.     call    count_out_err
  591. ;
  592. ;  setup lists for starting the RU on the chip
  593. ;  we know that there isn't anything in the buffer that we want
  594. ;
  595.  
  596.     mov    bx,firstfd        ; get first FD on free list (assume free)
  597.     mov    es:[SCB].scb_rfa,bx    ; put into SCB
  598.     mov    si,lastbd        ; pointer to a BD, end of chain
  599.     mov    ax,es:[si].rbd_link    ; pointer to next BD
  600.     mov    es:[bx].fd_ptr,ax    ; set to start of BDs
  601. ;
  602. ;
  603. ;  Start the RU, doesn't need CB, only SCB parms.
  604. ;   command, to start receiving again
  605. ;
  606.     mov    ax,10h            ; start RU
  607.     call    doca_wait
  608. hasres:
  609. ;I don't we need to wait here because we haven't done anything to wait for.
  610.     ret
  611.  
  612.  
  613.     public    recv_exiting
  614. recv_exiting:
  615. ;called from the recv isr after interrupts have been acknowledged.
  616. ;Only ds and ax have been saved.
  617.     assume    ds:nothing
  618.     ret
  619.  
  620.  
  621.     public    set_address
  622. set_address:
  623.     assume    ds:nothing
  624. ;enter with ds:si -> Ethernet address, CX = length of address.
  625. ;exit with nc if okay, or cy, dh=error if any errors.
  626.     cmp    cx,EADDR_LEN        ;ensure that their address is okay.
  627.     je    set_address_4
  628.     mov    dh,BAD_ADDRESS
  629.     stc
  630.     jmp    short set_address_done
  631. set_address_4:
  632.  
  633. ;  Next step, load our address into the board
  634. ;     reuses the space that the configure command used, with different command
  635. ;
  636.     mov    es,base_addr        ; set to base address
  637.     mov    es:[SCB].scb_cbl,CCBPTR    ; say where conf command is
  638.  
  639.     mov    di,CCBPTR        ; start of config command block
  640.     xor    ax,ax
  641.     stosw                ; zero status word for commmand
  642.     mov    ax,8001h        ; IA setup command + EL
  643.     stosw
  644.     xor    ax,ax
  645.     dec    ax
  646.     stosw                ; set link value to -1 (unused)
  647.  
  648.     rep    movsb            ; move their ethernet address in.
  649. ;
  650. ;  start the IA setup command
  651. ;
  652.     mov    ax,100h            ; do-command command
  653.     call    doca_wait
  654.     jnc    set_address_okay
  655.     mov    dh,-1            ; no error in the list applies.
  656.     jmp    short set_address_done
  657. set_address_okay:
  658.     mov    cx,EADDR_LEN        ;return their address length.
  659.     clc
  660. set_address_done:
  661.     push    cs
  662.     pop    ds
  663.     assume    ds:code
  664.     ret
  665.  
  666.  
  667. end_resident    label    byte
  668.  
  669. timeout_msg    db    "Timed out while initializing the board.",CR,LF,'$'
  670. our_address    db    6 dup(?)    ;temporarily hold our address
  671.  
  672. tdr_warn_msg    db    "TDR: ",'$'
  673. tdr_ok_msg    db    "Ok",CR,LF,'$'
  674. tdr_none_msg    db    "Ethernet card doesn't seem to be plugged in.",CR,LF,'$'
  675. tdr_open_msg    db    " clocks away is an OPEN (not completely reliable)",CR,LF,'$'
  676. tdr_short_msg    db    " clocks away is a SHORT (not completely reliable)",CR,LF,'$'
  677.  
  678. mem8_16        db    2        ; 1 for 16k, 2 for 8k
  679.  
  680.     extrn    set_recv_isr: near
  681.     extrn    maskint: near
  682.  
  683. ;enter with si -> argument string, di -> word to store.
  684. ;if there is no number, don't change the number.
  685.     extrn    get_number: near
  686.  
  687. ;enter with dx -> name of word, di -> dword to print.
  688.     extrn    print_number: near
  689.  
  690. ;enter with ax = number to print.
  691.     extrn    decout: near
  692.  
  693. timeout_error:
  694.     mov    dx,offset timeout_msg
  695.     jmp    short error
  696. error:
  697.     mov    ah,9
  698.     int    21h
  699.     stc
  700.     ret
  701.  
  702. ;
  703. ;  data for configuring and setting up the board
  704. ;
  705. ;  chip always looks at SCP for config info which points to ISCP for the
  706. ;  pointer to the CONTROL BLOCK which handles everything from there.
  707. ;  Kind of indirect, but it works.
  708. ;
  709. SCP    DB    0            ; bus use flag (0=16 bit, 1=8 bit).
  710.  
  711.     public    etopen
  712. etopen:
  713.     mov    al,int_no
  714.     call    maskint            ;disable these interrupts.
  715.  
  716. ;  Initialize the Ethernet board, set receive type.
  717. ;
  718. ;  check for correct EPROM location
  719. ;
  720.     call    check_board
  721.  
  722. ;
  723. ;  Turn off interrupts, I don't want them
  724. ;
  725.   ifdef IOINTOF
  726.     loadport
  727.     setport IOINTOF
  728.     out    dx,al
  729.   endif
  730. ;
  731. ;  Disconnect from network
  732. ;
  733.   ifdef IODIS
  734.     loadport
  735.     setport    IODIS
  736.     out    dx,al
  737.   endif
  738.  
  739. ;
  740. ;  Initialize the Ethernet board.
  741. ;
  742.     sub    base_addr,0e00h
  743.     mov    di,0e000h        ;our initial base address.
  744.     mov    si,ISCPTR-2        ;try the init down a little.
  745.  
  746. ;
  747. ;  Now discern the end of memory by repeatedly re-initializing the board
  748. ;  until the BUSY flag in the ISCP gets reset.
  749. ;
  750. re_discern:
  751.     mov    es,base_addr        ;remember where we think it starts.
  752.     call    init_root        ;did we find our memory size?
  753.     jc    confng            ;no, keep trying.
  754.     inc    si            ;yes, see if we found the real one.
  755.     inc    si
  756.     call    init_root        ;try initializing it in a different locn.
  757.     jnc    confok            ;it worked!  we've found the root.
  758.     dec    si            ;it didn't work, keep trying.
  759.     dec    si
  760. confng:
  761.     or    di,di            ;did we try all 64K?
  762.     je    confbad            ;yes.
  763.  
  764.     add    base_addr,200h        ;advance the segment by 2000h bytes.
  765.     sub    di,2000h        ;retreat the offset by 2000h bytes.
  766.     jmp    re_discern        ;try this next higher address.
  767. confbad:
  768.     sti
  769.     jmp    timeout_error
  770.  
  771. confok:
  772.     mov    memory_begin,di
  773.     call    reconfigure
  774.     jc    confbad
  775.  
  776. ;
  777. ;  Ask the board for the Ethernet address, and then use set_address to set it.
  778. ;
  779.     push    ds
  780.     pop    es
  781.     mov    di,offset our_address
  782.     mov    cx,EADDR_LEN
  783.     call    get_address
  784.  
  785.     mov    si,offset our_address
  786.     mov    cx,EADDR_LEN
  787.     call    set_address
  788.     jnc    store_address_2
  789.     sti
  790.     jmp    timeout_error
  791. store_address_2:
  792. ;
  793. ;  IA sent, setup all of the other data structures on the board
  794. ;  start with xmit command descriptors
  795. ;
  796.     mov    di,TCBPTR
  797.     mov    es:[di].tcb_status,0
  798.     mov    es:[di].tcb_com,08004h
  799.     mov    es:[di].tcb_link,-1
  800.     mov    es:[di].tcb_ptr,TBDPTR
  801.  
  802.     add    di,(size tcb_struc)
  803.  
  804.     mov    es:[di].tbd_status,0
  805.     mov    es:[di].tbd_link,0
  806.     mov    es:[di].tbd_ptr.offs,TBUFPTR
  807.     mov    es:[di].tbd_ptr.segm,0
  808.  
  809. ; Note that we allocate fd's, rbd's, and buffers all at the same time.  This
  810. ; doesn't mean that each pair of fd's and rbd's necessarily have anything to
  811. ; do with each other.  We just allocate them together because we want to have
  812. ; the same number of each, and it's easier to compute that way.
  813.  
  814.     mov    di,TBUFPTR        ;get the last buffer.
  815.  
  816.     mov    ax,di            ;compute the amount of free memory.
  817.     sub    ax,memory_begin
  818.     xor    dx,dx
  819.     mov    bx,RBUF_TOTAL        ;each buffer takes this much.
  820.     div    bx
  821.     mov    cx,ax            ;put the number of buffers into cx.
  822.  
  823. init_rbuff_0:
  824.     sub    di,RBUF_TOTAL        ;back the pointer down by a little.
  825.  
  826. ;init the FD.
  827.     mov    es:[di].fd_status,0
  828.     mov    es:[di].fd_eol,0
  829.     mov    es:[di].fd_ptr,-1
  830.     lea    ax,[di]-RBUF_TOTAL    ;get the address of the next buffer.
  831.     mov    es:[di].fd_link,ax
  832.  
  833. ;init the BD.
  834.     lea    bx,[di + (size fd_struc)]
  835.     mov    es:[bx].rbd_status,0
  836.     lea    ax,[bx-RBUF_TOTAL]    ;make a pointer to the next BD
  837.     mov    es:[bx].rbd_link,ax
  838.     lea    ax,[bx+(size rbd_struc)]    ;make a pointer to the buffer.
  839.     mov    es:[bx].rbd_ptr.offs,ax
  840.     mov    es:[bx].rbd_ptr.segm,0
  841.     mov    es:[bx].rbd_size,RBUFLEN    ;length of the buffer.
  842.  
  843.     loop    init_rbuff_0
  844.  
  845. init_rbuff_1:
  846. ;patch the parameters of the last FD and BD so they link around to the head.
  847.     mov    es:[di].fd_eol,8000h
  848.     mov    es:[di].fd_link,FDBASE
  849.     mov    lastfd,di
  850.  
  851.     lea    bx,[di + (size fd_struc)]
  852.     mov    es:[bx].rbd_link,FDBASE + (size fd_struc)
  853.     mov    es:[bx].rbd_size,RBUFLEN + 8000h
  854.     mov    lastbd,bx
  855.  
  856. ;now put the location of the first rbd into the first fd.
  857.     mov    es:[FDBASE].fd_ptr,FDBASE  + (size fd_struc)
  858.  
  859.     call    enable_network
  860.  
  861.     mov    dx,offset tdr_warn_msg    ;warn them that the 82586 TDR sucks.
  862.     mov    ah,9
  863.     int    21h
  864.  
  865. ;
  866. ; Test to see if the network is okay.
  867. ;
  868.     mov    di,CCBPTR        ; start of config command block
  869.     xor    ax,ax            ; zero status word for commmand
  870.     stosw
  871.     mov    ax,8005h        ; TDR command + EL
  872.     stosw
  873.     xor    ax,ax
  874.     dec    ax
  875.     stosw                ; set link value to -1 (unused)
  876.     inc    ax
  877.     stosw                ; zero time result.
  878.  
  879.     mov    ax,100h            ; do-command command
  880.     call    doca_wait
  881.     jnc    do_tdr_2        ; finished okay.
  882.     mov    ax,2000h        ; treat a timeout as an open
  883.     jmp    short do_tdr_5
  884. do_tdr_2:
  885.     mov    ax,word ptr es:[CCBPTR].tdr_time
  886. do_tdr_5:
  887.     mov    dx,offset tdr_ok_msg
  888.     test    ax,8000h
  889.     jne    do_tdr_3
  890.     mov    dx,offset tdr_short_msg
  891.     test    ax,2000h
  892.     je    do_tdr_4
  893.     mov    dx,offset tdr_none_msg
  894.     cmp    ax,2000h
  895.     je    do_tdr_3
  896.     mov    dx,offset tdr_open_msg
  897. do_tdr_4:
  898.     push    dx
  899.     and    ax,2048-1
  900.     xor    dx,dx
  901.     call    decout
  902.     pop    dx
  903. do_tdr_3:
  904.     mov    ah,9
  905.     int    21h
  906.  
  907. ;
  908. ;  Start the RU, doesn't need CB, only SCB parms.
  909. ;   command, to start receiving
  910. ;
  911.     mov    es:[SCB].scb_rfa,FDBASE    ; set to frame descriptors
  912.     mov    ax,10h            ; start RU
  913.     call    doca_wait
  914. ;
  915. ; Now reset CX, FR, CNA, and RNR so that we don't get a spurious interrupt.
  916. ;
  917.     mov    ax,es:[SCB].scb_stat    ;get the status.
  918.     and    ax,0f000h        ;isolate the ACK bits.
  919.     mov    es:[SCB].scb_com,ax    ;make a command to
  920.                     ;acknowledge the interrupt.
  921.     call    doca
  922. ;
  923. ; Now hook in our interrupt
  924. ;
  925.     call    set_recv_isr
  926.  
  927.     sti
  928.  
  929.     mov    al, int_no        ; Get board's interrupt vector
  930.     add    al, 8
  931.     cmp    al, 8+8            ; Is it a slave 8259 interrupt?
  932.     jb    set_int_num        ; No.
  933.     add    al, 70h - 8 - 8        ; Map it to the real interrupt.
  934. set_int_num:
  935.     xor    ah, ah            ; Clear high byte
  936.     mov    int_num, ax        ; Set parameter_list int num.
  937.  
  938.     mov    dx,offset end_resident
  939.     clc
  940.     ret
  941.  
  942.  
  943. init_root:
  944. ;enter with es:di -> beginning of our system memory window,
  945. ;  si -> place to put ISC.
  946. ;exit with nc if it worked, cy if it didn't work.
  947.  
  948.     mov    al,SCP
  949.     mov    es:[SCPTR].scp_bus,al
  950.     mov    es:[SCPTR].scp_ptr.offs,si
  951.     mov    es:[SCPTR].scp_ptr.segm,0
  952.  
  953.     mov    es:[si].iscp_busy,1        ;set busy bit.
  954.     mov    es:[si].iscp_offset,SCB        ;point to the SCB.
  955.     mov    es:[si].iscp_base.offs,0    ;scb base.
  956.     mov    es:[si].iscp_base.segm,0    ;scb base.
  957.  
  958.     call    reset_586        ; reset the 586, hardware-specific.
  959.  
  960. ;
  961. ;  Issue a CA to initialize the chip after reset
  962. ;
  963.     call    doca
  964.  
  965.     mov    ax,2            ;don't wait too long.
  966.     call    set_timeout
  967. init_root_2:
  968.     cmp    es:[si].iscp_busy,0    ;did it clear the busy flag?
  969.     je    init_root_1        ;yes.
  970.     call    do_timeout
  971.     jne    init_root_2
  972.     stc
  973.     ret
  974. init_root_1:
  975.     clc
  976.     ret
  977.